/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

// autor(a): lari
package SintaticoPacote;
//

import compilador_full.TabelaSimbolos;
import java.util.Enumeration;


public class CodigoFonte {


    // núcleo Sintático
    public boolean Compilator (TabelaSimbolos tabelasimbolos) {
        // starta lookahead
        tabelasimbolos.ZeraLookahead();
        boolean retorno = true;

        //cria os objetos
        declaracaoBibliotecas bibliotecas = new declaracaoBibliotecas();
        declaracaoConstantes constantes = new declaracaoConstantes();
        Tipos tipoTipo = new Tipos();
        declaracaoStructs struct = new declaracaoStructs(tabelasimbolos);
        declaracaoVariaveis variaveis = new declaracaoVariaveis(tabelasimbolos);
        declaracaoPonteiros ponteiros = new declaracaoPonteiros(tabelasimbolos);
        declaracaoMetodos metodos = new declaracaoMetodos();
        declaracaoMetodosVoid metodosVoid = new declaracaoMetodosVoid();
        declaracaoMetodoMain metodoMain = new declaracaoMetodoMain();


        // Verifica bibliotecas
        while (tabelasimbolos.getLookahead().equals("include")){
            retorno = bibliotecas.declaraBibliotecas(tabelasimbolos);
        }
        // Verifica constantes
        while (tabelasimbolos.getLookahead().equals("const")){
            tabelasimbolos.salvaEscopo("global");

            retorno = constantes.declaraConstantes(tabelasimbolos);
        }

        //verifica delcaração de struct, variaveis e ponteiros que começam por typedef, struct ou é do tipo "tipos"
        while(tabelasimbolos.getLookahead().equals("typedef") || tabelasimbolos.getLookahead().equals("struct") || (Tipos.apenasCompara(tabelasimbolos) && (!tabelasimbolos.superLookahead(2).equals("(")))){

                if(tabelasimbolos.getLookahead().equals("struct")) {

                        // salva escopo
                        tabelasimbolos.salvaEscopo("struct");
                        // salva escopo
                        tabelasimbolos.salvaEscopo2("global");
			retorno = struct.declaraStructs();

                } else if ( tabelasimbolos.getLookahead().equals("typedef")){
			if(tabelasimbolos.superLookahead(1).equals("struct")) {
                                // salva escopo
                                tabelasimbolos.salvaEscopo("struct");
                                // salva escopo
                                tabelasimbolos.salvaEscopo2("global");
				retorno = struct.declaraStructs();

                        }else if(Tipos.isDentroDeTipo(tabelasimbolos,1)) {
                                // salva escopo
                                tabelasimbolos.salvaEscopo("global");
				retorno = variaveis.declaraVariaveis();
                        }
		}

		else if (Tipos.apenasCompara(tabelasimbolos)){//se look estah dentro de tipos
			if((tabelasimbolos.superTipo(1).equals("identificador") && !tabelasimbolos.superLookahead(2).equals("("))||tabelasimbolos.superLookahead(1).equals("*")){

                                tabelasimbolos.salvaEscopo("global");
                                retorno = variaveis.declaraVariaveis();
                        }


//			else if(tabelasimbolos.superLookahead(1).equals("*") && tabelasimbolos.superTipo(2).equals("identificador") && !tabelasimbolos.superLookahead(3).equals("(")||(tabelasimbolos.superLookahead(1).equals("*")&&tabelasimbolos.superLookahead(2).equals("*"))){
//                                tabelasimbolos.salvaEscopo("global");
//				retorno = ponteiros.declaraPonteiros();
//
//                        }else

			else if(tabelasimbolos.superLookahead(1).equals("*") && tabelasimbolos.superTipo(2).equals("identificador") && !tabelasimbolos.superLookahead(3).equals("(")||(tabelasimbolos.superLookahead(1).equals("*")&&tabelasimbolos.superLookahead(2).equals("*")))
				retorno = ponteiros.declaraPonteiros();

                        else

                            break;
		}
                else
                    break;
	}

        while(Tipos.apenasCompara(tabelasimbolos) || (tabelasimbolos.getLookahead().equals("void") && !tabelasimbolos.superLookahead(1).equals("main"))){

		if(!tabelasimbolos.getLookahead().equals("void") &&
                    ((tabelasimbolos.superLookahead(1).equals("*") && tabelasimbolos.superTipo(2).equals("identificador") && tabelasimbolos.superLookahead(3).equals("(")) ||
                    (tabelasimbolos.superTipo(1).equals("identificador") && tabelasimbolos.superLookahead(2).equals("(") ))){

            tabelasimbolos.salvaEscopo("global");
			retorno = metodos.declaraMetodos(tabelasimbolos);

		}else if( tabelasimbolos.getLookahead().equals("void") && tabelasimbolos.superTipo(1).equals("identificador"))
                {
            tabelasimbolos.salvaEscopo("global");
			retorno = metodosVoid.declaracaoMetodosVoid(tabelasimbolos);
                }
                else
                      break;
	}

        tabelasimbolos.salvaEscopo("main");
	retorno = metodoMain.declaracaoMetodoMain(tabelasimbolos);

        System.out.println("fim : " + tabelasimbolos.getLookahead());
        if(tabelasimbolos.getLookahead().equals("")){
            System.out.println("ok");
        }
        else
           return false; //se nao achar }



/*
        Enumeration<String> enums = tabelasimbolos.getEscopo2().elements();

        System.out.println("******");
        whileSystem.out.println("******");(enums.hasMoreElements())
        {
            System.out.println(enums.nextElement());
        }
*/
        //
        System.out.println("******************");
        // Imprimir os valores correspondentes
        for (int i = 0; i < tabelasimbolos.getponteiroSize(); i ++) {
             String categoria = "";
             String escopo = "";
             String tipovariavel = "";

             if (tabelasimbolos.getTabelaEscopo().containsKey(i) || tabelasimbolos.getTabelaCategoria().containsKey(i) || tabelasimbolos.getTabelaTipoVariavel().containsKey(i)) {
                 if (tabelasimbolos.getTabelaEscopo().containsKey(i))
                     escopo = tabelasimbolos.getTabelaEscopo().get(i);

                 if (tabelasimbolos.getTabelaCategoria().containsKey(i))
                     categoria = tabelasimbolos.getTabelaCategoria().get(i);

                 if (tabelasimbolos.getTabelaTipoVariavel().containsKey(i))
                     tipovariavel = tabelasimbolos.getTabelaTipoVariavel().get(i);

                 System.out.println("Lexema: " + tabelasimbolos.getLexema(i)+ "   -  Escopo: " + escopo + " - Categoria: " + categoria + " -  TipoVariavel: " + tipovariavel);
             }
             //
        }



//        Enumeration<String> enums2 = tabelasimbolos.getTipoVariavel().elements();
//
//        System.out.println("++++++");
//        while(enums2.hasMoreElements())
//        {
//            System.out.println(enums2.nextElement());
//        }

        return retorno;

    }




}
